package main

import (
	"fmt"
	"math"
	"sort"
)

func main() {
	c := NewCircle(2)
	fmt.Println(c, c.Area()) // 圆形
	t := NewTriangle(2, 3)
	fmt.Println(t, t.Area()) // 三角形
	r := NewRectangle(2, 3)
	fmt.Println(r, r.Area()) // 长方形

	fmt.Println("~~~~~~~~~~~~~分割线~~~~~~~~~~~~~~")
	var i Interface = c
	fmt.Println(i.Area())
	i = t
	fmt.Println(i.Area())

	var shapes = []Interface{c, t, r}
	fmt.Println(shapes)
	sort.Slice(shapes, func(i, j int) bool {
		return shapes[i].Area() > shapes[j].Area()
	}) 
	fmt.Println(shapes) 

	for i, v := range shapes {
		fmt.Println(i, v, v.Area())
	}
}

type Interface interface {
	Area() float32 // 图形面积方法
}
type Shape struct {
	area float32 // 记录已经计算过的结果
}


type Circle struct {
	Shape
	r float32 // 半径
}

// 构造函数
func NewCircle(r float32) *Circle {
	return &Circle{r: r}
}
func (c *Circle) Area() float32 {
	if c.area == 0 {
		c.area = math.Pi * c.r * c.r
	}
	return c.area
}

// 三角形
type Triangle struct {
	base, height float32
	Shape
}

func NewTriangle(base, height float32) *Triangle {
	return &Triangle{base: base, height: height}
}
func (t *Triangle) Area() float32 {
	if t.area == 0 {
		t.area = t.base * t.height / 2
	}
	return t.area
}

// 长方形
type Rectangle struct {
	width, height float32
	Shape
}

func NewRectangle(width, height float32) *Rectangle {
	return &Rectangle{width, height, Shape{}}
}
func (r *Rectangle) Area() float32 {
	if r.area == 0 {
		r.area = r.width * r.height
	}
	return r.area
}
